package com.xinchao.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xinchao.cache.RedisCacheDao;
import com.xinchao.constant.*;
import com.xinchao.dao.AdvertisementMapper;
import com.xinchao.exception.ServiceException;
import com.xinchao.model.Advertisement;
import com.xinchao.model.OperationLog;
import com.xinchao.model.User;
import com.xinchao.model.dto.AdvertisementApiDTO;
import com.xinchao.model.dto.AdvertisementListDTO;
import com.xinchao.model.page.PageInfo;
import com.xinchao.model.sys.JsonResponse;
import com.xinchao.service.AdvertisementService;
import com.xinchao.service.OperationLogService;
import com.xinchao.util.UUIDUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author dxy
 * @date 2018/9/18 18:35
 */
@Service(value = "advertisementService")
public class AdvertisementServiceImpl implements AdvertisementService {
	@Autowired
	private AdvertisementMapper advertisementMapper;
	@Autowired
	private OperationLogService operationLogService;
	@Autowired
	private RedisCacheDao redisCacheDao;

	/**
	 * 保存广告
	 * @param advertisement Advertisement
	 * @param loginUser     User
	 * @param remoteIP      远程ip
	 * @throws ServiceException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveAdvertisement(Advertisement advertisement, User loginUser, String remoteIP) throws ServiceException {
		if (advertisement == null || loginUser == null || StringUtils.isBlank(remoteIP)) {
			throw new ServiceException("输入参数不能为空");
		}
		//保存广告
		advertisement.setAdvertisementCode(UUIDUtils.getUUIDString());
		advertisement.setAddTime(System.currentTimeMillis());
		advertisement.setStatus(BusinessConstant.STATUS_ENABLE);
		advertisementMapper.insertAdvertisement(advertisement);
		//记录操作日志
		OperationLog operationLog = new OperationLog();
		operationLog.setOperationContent("保存广告，广告名称为: " + advertisement.getAdvertisementName());
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setOperationModule(ModuleConstant.MODULE_ADVERTISEMENT + "-" + ModuleConstant.MODULE_ADVERTISEMENT_LIST);
		operationLog.setRealname(loginUser.getRealname());
		operationLog.setUserName(loginUser.getUserName());
		operationLog.setOperationIp(remoteIP);
		operationLogService.saveOperationLog(operationLog);
	}

	/**
	 * 保存广告并加入缓存
	 *
	 * @param advertisement Advertisement
	 * @param loginUser     User
	 * @param remoteIP      远程ip
	 * @throws ServiceException
	 */
	@Override
	public void saveAdvertisementFlushCache(Advertisement advertisement, User loginUser, String remoteIP) throws ServiceException {
		if (advertisement == null || loginUser == null || StringUtils.isBlank(remoteIP)) {
			throw new ServiceException("输入参数不能为空");
		}
		//保存广告
		saveAdvertisement(advertisement, loginUser, remoteIP);
		//广告状态
		Integer advertisementStatus = advertisement.getAdvertisementStatus();
		if (advertisementStatus != null) {
			//如果广告状态为上线状态，刷新缓存
			if (AdvertisementConstant.ADVERTISEMENT_STATUS_ONLINE == advertisementStatus) {
				//刷新广告缓存
				flushAdvertisementCache(advertisement);
			}
		}
	}


	/**
	 * 修改广告
	 * @param advertisement Advertisement
	 * @param loginUser     User
	 * @param remoteIP      远程ip
	 * @throws ServiceException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void updateAdvertisementById(Advertisement advertisement, User loginUser, String remoteIP) throws ServiceException {
		if (advertisement == null || loginUser == null || StringUtils.isBlank(remoteIP)) {
			throw new ServiceException("输入参数不能为空");
		}
		if (advertisement.getAdvertisementId() == null) {
			throw new ServiceException("广告ID不能为空");
		}
		//修改广告
		advertisementMapper.updateAdvertisementById(advertisement);
		//记录操作日志
		OperationLog operationLog = new OperationLog();
		operationLog.setOperationContent("修改广告，广告名称为: " + advertisement.getAdvertisementName());
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setOperationModule(ModuleConstant.MODULE_ADVERTISEMENT + "-" + ModuleConstant.MODULE_ADVERTISEMENT_LIST);
		operationLog.setRealname(loginUser.getRealname());
		operationLog.setUserName(loginUser.getUserName());
		operationLog.setOperationIp(remoteIP);
		operationLogService.saveOperationLog(operationLog);
	}

	/**
	 * 修改广告并放入缓存
	 *
	 * @param advertisement Advertisement
	 * @param loginUser     User
	 * @param remoteIP      远程ip
	 * @throws ServiceException
	 */
	@Override
	public void updateAdvertisementFlushCache(Advertisement advertisement, User loginUser, String remoteIP) throws ServiceException {
		if (advertisement == null) {
			throw new ServiceException("输入参数不能为空");
		}
		if (advertisement.getAdvertisementId() == null) {
			throw new ServiceException("广告ID不能为空");
		}
		//获取原广告
		Advertisement oldAdvertisement = advertisementMapper.getAdvertisementById(advertisement.getAdvertisementId());
		if (oldAdvertisement == null) {
			throw new ServiceException("广告数据不存在，请联系管理员");
		}
		//通过广告ID修改广告
		updateAdvertisementById(advertisement, loginUser, remoteIP);

		//如果年龄和性别有修改，需要更新以前的缓存
		String oldAge = oldAdvertisement.getAge();
		Integer oldSex = oldAdvertisement.getSex();
		if (StringUtils.isNotBlank(oldAge) && oldSex != null) {
			if (!oldAge.equals(advertisement.getAge()) || !oldSex.equals(advertisement.getSex())) {
				String[] ageArray = oldAge.split(",");
				if (ageArray != null && ageArray.length > 0) {
					for (int i = 0; i < ageArray.length; i++) {
						String age = ageArray[i];
						//缓存名
						String cacheName = "";
						//男性
						if (AdvertisementConstant.SEX_MALE == oldSex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_MALE;
						}
						//女性
						if (AdvertisementConstant.SEX_FEMALE == oldSex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_FEMALE;
						}
						//不限性别
						if (AdvertisementConstant.SEX_NO == oldSex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_NO;
						}
						//获取key
						String key = AdvertisementConstant.AGE_RANGE_MAP.get(age);
						redisCacheDao.deleteByKey(cacheName, key);
					}
				}
			}
		}
		//刷新广告缓存
		flushAdvertisementCache(advertisement);
	}

	/***
	 * 通过ID删除广告
	 * @param advertisementId 广告ID
	 * @param loginUser       User
	 * @param remoteIP        远程ip
	 * @throws ServiceException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void deleteAdvertisementById(Long advertisementId, User loginUser, String remoteIP) throws ServiceException {
		if (advertisementId == null || loginUser == null || StringUtils.isBlank(remoteIP)) {
			throw new ServiceException("输入参数不能为空");
		}
		Advertisement oldAdvertisement = advertisementMapper.getAdvertisementById(advertisementId);
		if (oldAdvertisement == null) {
			throw new ServiceException("广告数据不存在，请联系管理员");
		}
		Advertisement advertisement = new Advertisement();
		//将广告主ID设置为null，解除广告主和广告的关联关系
		advertisement.setAdvertiserId(null);
		advertisement.setAdvertisementId(advertisementId);
		advertisement.setStatus(BusinessConstant.STATUS_DISABLE);
		advertisement.setUpdateTime(System.currentTimeMillis());
		advertisementMapper.updateAdvertisementById(advertisement);
		//记录操作日志
		OperationLog operationLog = new OperationLog();
		operationLog.setOperationContent("删除广告，广告名称为: " + oldAdvertisement.getAdvertisementName());
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setOperationModule(ModuleConstant.MODULE_ADVERTISEMENT + "-" + ModuleConstant.MODULE_ADVERTISEMENT_LIST);
		operationLog.setRealname(loginUser.getRealname());
		operationLog.setUserName(loginUser.getUserName());
		operationLog.setOperationIp(remoteIP);
		operationLogService.saveOperationLog(operationLog);
	}

	/**
	 * 通过ID删除广告并刷新缓存
	 *
	 * @param advertisementId 广告ID
	 * @param loginUser       User
	 * @param remoteIP        远程ip
	 * @throws ServiceException
	 */
	@Override
	public void deleteAdvertisementFlushCache(Long advertisementId, User loginUser, String remoteIP) throws ServiceException {
		//根据广告ID获取广告
		Advertisement oldAdvertisement = advertisementMapper.getAdvertisementById(advertisementId);
		if (oldAdvertisement == null) {
			throw new ServiceException("广告数据不存在，请联系管理员");
		}
		//删除广告
		deleteAdvertisementById(advertisementId, loginUser, remoteIP);
		//刷新广告缓存
		flushAdvertisementCache(oldAdvertisement);
	}

	/**
	 * 获取广告列表
	 *
	 * @param advertiserName      广告主名称
	 * @param advertisementName   广告名称
	 * @param advertisementStatus 广告状态
	 * @param sex                 性别
	 * @param age                 年龄
	 * @param pageNum             当前页
	 * @param pageSize            每页条数
	 * @return PageInfo<AdvertisementListDTO>
	 */
	@Override
	@Transactional(readOnly = true, rollbackFor = Exception.class)
	public PageInfo<AdvertisementListDTO> listAdvertisement(String advertiserName, String advertisementName, Integer advertisementStatus,
	                                                        Integer sex, String age, Integer pageNum, Integer pageSize) {
		//设置默认值
		if (pageNum == null) {
			pageNum = PageConstant.DEFAULT_PAGE_NUM;
		}
		if (pageSize == null) {
			pageSize = PageConstant.DEFAULT_PAGE_SIZE;
		}
		PageHelper.startPage(pageNum, pageSize);
		Page<AdvertisementListDTO> page = advertisementMapper.listAdvertisement(advertiserName, advertisementName, advertisementStatus, sex, age);
		PageInfo<AdvertisementListDTO> pageInfo = new PageInfo<>();
		if (page == null) {
			return pageInfo;
		}
		pageInfo.setPageNum(page.getPageNum());
		pageInfo.setPageSize(page.getPageSize());
		pageInfo.setTotal(page.getTotal());
		pageInfo.setList(page.getResult());
		return pageInfo;
	}

	/**
	 * 通过广告主ID获取广告条数
	 * @param advertiserId 广告主ID
	 * @return Long
	 * @throws ServiceException
	 */
	@Override
	public Long countAdvertisementByAdvertiserId(Long advertiserId) throws ServiceException {
		if (advertiserId == null) {
			throw new ServiceException("输入参数不能为空");
		}
		return advertisementMapper.countAdvertisementByAdvertiserId(advertiserId);
	}

	/**
	 * 通过广告名称获取广告
	 * @param advertisementName 广告名称
	 * @return Advertisement
	 */
	@Override
	public Advertisement getAdvertisementByAdvertisementName(String advertisementName) throws ServiceException {
		if (StringUtils.isBlank(advertisementName)) {
			throw  new ServiceException("广告名称不能为空");
		}
		return advertisementMapper.getAdvertisementByAdvertisementName(advertisementName);
	}


	/**
	 * 验证广告
	 * @param advertisement Advertisement
	 * @return JsonResponse
	 */
	@Override
	public JsonResponse validateAdvertisement(Advertisement advertisement) {
		//广告名称
		if (advertisement.getAdvertisementStatus() == null) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "广告状态不能为空，请选择广告状态");
		}
		String advertisementName = advertisement.getAdvertisementName();
		//广告名称
		if (StringUtils.isBlank(advertisementName)) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "广告名称不能为空，请输入广告名称");
		}
		//广告名称
		if (StringUtils.isBlank(advertisement.getAdvertisementBrand())) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "广告品牌不能为空，请输入广告品牌");
		}
		//视频是否上传
		if (StringUtils.isBlank(advertisement.getTopVideoURL())) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "请上传上屏视屏");
		}
		//图片是否上传
		if (StringUtils.isBlank(advertisement.getBottomImageURL())) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "请上传下屏图片");
		}
		//是否是品宣广告
		Integer declareGoodsAdvertisement = advertisement.getDeclareGoodsAdvertisement();
		if (declareGoodsAdvertisement == null) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "是否是品宣广告不能为空");
		}
		//广告状态
		if (advertisement.getAdvertisementStatus() == null) {
			return new JsonResponse(ResponseConstant.CODE_FAIL, "广告状态不能为空");
		}
		//如果不是品宣广告，需要验证广告主、年龄、性别
		if (AdvertisementConstant.DECLARE_GOODS_ADVERTISEMENT_NO == declareGoodsAdvertisement) {
			//广告主
			if (advertisement.getAdvertiserId() == null) {
				return new JsonResponse(ResponseConstant.CODE_FAIL, "广告主不能为空，请选择广告主");
			}
			//年龄
			if (StringUtils.isBlank(advertisement.getAge())) {
				return new JsonResponse(ResponseConstant.CODE_FAIL, "年龄不能为空，请选择年龄");
			}
			//年龄
			if (advertisement.getSex() == null) {
				return new JsonResponse(ResponseConstant.CODE_FAIL, "性别不能为空，请选择性别");
			}
		}
		return null;
	}

	/**
	 * 更新广告状态
	 *
	 * @param advertisementId     广告ID
	 * @param advertisementStatus 广告状态
	 * @param loginUser           User
	 * @param remoteIP            远程ip
	 * @throws ServiceException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void updateAdvertisementStatusById(Long advertisementId, String advertisementName, Integer advertisementStatus, User loginUser, String remoteIP) throws ServiceException {
		if (advertisementStatus == null || StringUtils.isBlank(advertisementName)
				|| loginUser == null || StringUtils.isBlank(remoteIP)) {
			throw new ServiceException("输入参数不能为空");
		}
		advertisementMapper.updateAdvertisementStatus(advertisementId, advertisementStatus);
		//记录操作日志
		OperationLog operationLog = new OperationLog();
		//广告状态中文解释
		String advertisementStatusStr = AdvertisementConstant.ADVERTISEMENT_STATUS_MAP.get(advertisementStatus);
		operationLog.setOperationContent(advertisementName + "的状态被更改为：" + advertisementStatusStr);
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setOperationModule(ModuleConstant.MODULE_ADVERTISEMENT + "-" + ModuleConstant.MODULE_ADVERTISEMENT_LIST);
		operationLog.setRealname(loginUser.getRealname());
		operationLog.setUserName(loginUser.getUserName());
		operationLog.setOperationIp(remoteIP);
		operationLogService.saveOperationLog(operationLog);
	}

	/**
	 * 更新广告状态并添加至缓存或从缓存中移除
	 *
	 * @param advertisementId     广告ID
	 * @param advertisementName   广告名称
	 * @param advertisementStatus 广告状态
	 * @param loginUser           User
	 * @param remoteIP            远程ip
	 */
	@Override
	public void updateAdvertisementStatusFlushCache(Long advertisementId, String advertisementName, Integer advertisementStatus, User loginUser, String remoteIP) throws ServiceException {
		//更新广告状态
		updateAdvertisementStatusById(advertisementId, advertisementName, advertisementStatus, loginUser, remoteIP);
		//根据广告ID获取广告
		Advertisement oldAdvertisement = advertisementMapper.getAdvertisementById(advertisementId);
		if (oldAdvertisement == null) {
			throw new ServiceException("广告数据不存在，请联系管理员");
		}
		//修改缓存
		flushAdvertisementCache(oldAdvertisement);
	}

	/**
	 * 通过ID获取广告
	 * @param advertisementId 广告ID
	 * @return Advertisement
	 */
	@Override
	public Advertisement getAdvertisementById(Long advertisementId) {
		if (advertisementId == null) {
			return null;
		}
		return advertisementMapper.getAdvertisementById(advertisementId);
	}

	/**
	 * 获取所有广告名称
	 * @return List<String>
	 */
	@Override
	public List<String> listAllAdvertisementName() {
		return advertisementMapper.listAllAdvertisementName();
	}

	/**
	 * 获取广告总数
	 * @return Long
	 */
	@Override
	public Long countAdvertisement() {
		return advertisementMapper.countAdvertisement();
	}

	/**
	 * 将广告放入缓存
	 * @param advertisement Advertisement
	 */
	private void flushAdvertisementCache(Advertisement advertisement) {
		if (advertisement != null) {
			//性别
			Integer sex = advertisement.getSex();
			//年龄
			String ageRange = advertisement.getAge();
			if (sex != null && StringUtils.isNotBlank(ageRange)) {
				String[] ageArray = ageRange.split(",");
				if (ageArray != null && ageArray.length > 0) {
					for (int i = 0; i < ageArray.length; i++) {
						String age = ageArray[i];
						//缓存名
						String cacheName = "";
						//男性
						if (AdvertisementConstant.SEX_MALE == sex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_MALE;
						}
						//女性
						if (AdvertisementConstant.SEX_FEMALE == sex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_FEMALE;
						}
						//不限性别
						if (AdvertisementConstant.SEX_NO == sex) {
							cacheName = CacheConstant.CACHE_NAME_SEX_NO;
						}
						//广告列表
						List<AdvertisementApiDTO> advertisementList = advertisementMapper.listAdvertisementByAgeAndSex(age, sex, AdvertisementConstant.DECLARE_GOODS_ADVERTISEMENT_NO);
						if (CollectionUtils.isNotEmpty(advertisementList)) {
							//获取key
							String key = AdvertisementConstant.AGE_RANGE_MAP.get(age);
							//放入redis缓存
							redisCacheDao.putCache(cacheName, key, advertisementList);
						}
					}
				}
			}
		}
	}
}
